The "big treeview focus patch". Fixes several issues and adds some
authorKristian Rietveld <kris@gtk.org>
Sun, 5 May 2002 14:54:00 +0000 (14:54 +0000)
committerKristian Rietveld <kristian@src.gnome.org>
Sun, 5 May 2002 14:54:00 +0000 (14:54 +0000)
Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>

        The "big treeview focus patch". Fixes several issues and adds some
        goodies. Related bugs: #73676, #73734, #78660.

        * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell

        * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
        if applicable,
        (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
        add support for row-spanning focus rectangles,
        (gtk_tree_view_has_special_cell): new function,
        (gtk_tree_view_move_cursor_left_right): add support for multiple
        focusable cells in one column,
        (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
        (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
        with focus_cell parameter,
        (gtk_tree_view_search_iter): removed unused column variable,
        (gtk_tree_view_start_editing): add neighbor size code to allow
        for multiple editable cells in one column.

        * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
        in_editing_mode field,
        (gtk_tree_view_column_get_edited_cell): new function, removed
        _get_editable_cell,
        (_gtk_tree_view_column_get_cell_at_pos): new function,
        (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
        (gtk_tree_view_column_cell_process_action): loads of changes to get
        it right and to allow for multiple special cells, etc,
        (gtk_tree_view_column_cell_first): new function,
        (gtk_tree_view_column_cell_last): ditto,
        (gtk_tree_view_column_cell_next): ditto,
        (gtk_tree_view_column_cell_prev): ditto,
        (gtk_tree_view_column_cell_focus): add left and right parameters,
        allow for multiple special cells,
        (gtk_tree_view_column_cell_is_visible): add assertion,
        (gtk_tree_view_column_focus_cell): new function,
        (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
        (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
        correctly

        * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell

        * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
        _gtk_tree_view_column_get_cell_at_pos, add new parameters to
        _gtk_tree_view_column_cell_focus.

        * tests/testtreeedit.c: add some cells in order to test new code.

12 files changed:
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtktreeprivate.h
gtk/gtktreeview.c
gtk/gtktreeview.h
gtk/gtktreeviewcolumn.c
gtk/gtktreeviewcolumn.h
tests/testtreeedit.c

index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index e8914e6f816b700fc8dbce021e5d5366004a81eb..90915b7314647828c5f059b461aa6e11eae91a64 100644 (file)
@@ -1,3 +1,52 @@
+Sun May  5 16:42:32 2002  Kristian Rietveld  <kris@gtk.org>
+
+       The "big treeview focus patch". Fixes several issues and adds some
+       goodies. Related bugs: #73676, #73734, #78660.
+
+       * gtk/gtktreeview.h: add gtk_tree_view_set_cursor_on_cell
+
+       * gtk/gtktreeview.c (gtk_tree_view_button_press): focus on a cell
+       if applicable,
+       (gtk_tree_view_bin_expose): set_cell_data before iterating columns,
+       add support for row-spanning focus rectangles,
+       (gtk_tree_view_has_special_cell): new function,
+       (gtk_tree_view_move_cursor_left_right): add support for multiple
+       focusable cells in one column,
+       (gtk_tree_view_set_cursor): call _set_cursor_on_cell now,
+       (gtk_tree_view_set_cursor_on_cell): copy of _set_cursor, extended
+       with focus_cell parameter,
+       (gtk_tree_view_search_iter): removed unused column variable,
+       (gtk_tree_view_start_editing): add neighbor size code to allow
+       for multiple editable cells in one column.
+
+       * gtk/gtktreeviewcolumn.c (_GtkTreeViewColumnCellInfo): add
+       in_editing_mode field,
+       (gtk_tree_view_column_get_edited_cell): new function, removed
+       _get_editable_cell,
+       (_gtk_tree_view_column_get_cell_at_pos): new function,
+       (gtk_tree_view_column_pack_end): s/g_new/g_new0/ ...,
+       (gtk_tree_view_column_cell_process_action): loads of changes to get
+       it right and to allow for multiple special cells, etc,
+       (gtk_tree_view_column_cell_first): new function,
+       (gtk_tree_view_column_cell_last): ditto,
+       (gtk_tree_view_column_cell_next): ditto,
+       (gtk_tree_view_column_cell_prev): ditto,
+       (gtk_tree_view_column_cell_focus): add left and right parameters,       
+       allow for multiple special cells,
+       (gtk_tree_view_column_cell_is_visible): add assertion,
+       (gtk_tree_view_column_focus_cell): new function,
+       (gtk_tree_view_column_stop_editing): unset in_editing_mode flag,
+       (_gtk_tree_view_column_get_neighbor_sizes): iterate through cells
+       correctly
+
+       * gtk/gtktreeviewcolumn.h: add gtk_tree_view_column_focus_cell
+
+       * gtk/gtktreeprivate.h: s/_get_editable_cell/_get_edited_cell/, add
+       _gtk_tree_view_column_get_cell_at_pos, add new parameters to
+       _gtk_tree_view_column_cell_focus.
+
+       * tests/testtreeedit.c: add some cells in order to test new code.
+
 Sun May  5 02:22:59 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * tests/test-images/*: image files for testing pixbuf loaders
index 8abd5657b3931d39d36622b88cfdb40ce4b38371..5f01013197a2bec93bfd6e051804b0689d28e0c8 100644 (file)
@@ -316,8 +316,10 @@ void             _gtk_tree_view_column_autosize          (GtkTreeView       *tre
                                                          GtkTreeViewColumn *column);
 
 gboolean         _gtk_tree_view_column_has_editable_cell (GtkTreeViewColumn *column);
-GtkCellRenderer *_gtk_tree_view_column_get_editable_cell (GtkTreeViewColumn *column);
+GtkCellRenderer *_gtk_tree_view_column_get_edited_cell   (GtkTreeViewColumn *column);
 gint             _gtk_tree_view_column_count_special_cells (GtkTreeViewColumn *column);
+GtkCellRenderer *_gtk_tree_view_column_get_cell_at_pos   (GtkTreeViewColumn *column,
+                                                         gint               x);
 
 GtkTreeSelection* _gtk_tree_selection_new                (void);
 GtkTreeSelection* _gtk_tree_selection_new_with_tree_view (GtkTreeView      *tree_view);
@@ -331,7 +333,9 @@ void                  _gtk_tree_view_column_cell_render      (GtkTreeViewColumn *tree_column,
                                                          GdkRectangle      *expose_area,
                                                          guint              flags);
 gboolean         _gtk_tree_view_column_cell_focus       (GtkTreeViewColumn *tree_column,
-                                                         gint               direction);
+                                                         gint               direction,
+                                                         gboolean           left,
+                                                         gboolean           right);
 void             _gtk_tree_view_column_cell_draw_focus  (GtkTreeViewColumn *tree_column,
                                                          GdkWindow         *window,
                                                          GdkRectangle      *background_area,
index 4e6cfd482c8bfe04c10d13cfa69fdfe4cd5a2908..e1bcaa31d65f9a53d4753b44c5b7b47c95660654 100644 (file)
@@ -347,6 +347,7 @@ static void     gtk_tree_view_real_set_cursor                (GtkTreeView
                                                              GtkTreePath       *path,
                                                              gboolean           clear_and_select,
                                                              gboolean           clamp_node);
+static gboolean gtk_tree_view_has_special_cell               (GtkTreeView       *tree_view);
 
 /* interactive search */
 static void     gtk_tree_view_search_dialog_destroy     (GtkWidget        *search_dialog,
@@ -1709,6 +1710,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       gint dval;
       gint pre_val, aft_val;
       GtkTreeViewColumn *column = NULL;
+      GtkCellRenderer *focus_cell = NULL;
       gint column_handled_click = FALSE;
       gboolean emit_row_activated = FALSE;
 
@@ -1829,7 +1831,7 @@ gtk_tree_view_button_press (GtkWidget      *widget,
                      GdkRectangle area;
 
                      area = cell_area;
-                     _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_editable_cell (column), &left, &right);
+                     _gtk_tree_view_column_get_neighbor_sizes (column, _gtk_tree_view_column_get_edited_cell (column), &left, &right);
 
                      area.x += left;
                      area.width -= right + left;
@@ -1857,6 +1859,10 @@ gtk_tree_view_button_press (GtkWidget      *widget,
       pre_val = tree_view->priv->vadjustment->value;
 
       tree_view->priv->focus_column = column;
+      focus_cell = _gtk_tree_view_column_get_cell_at_pos (column, event->x - background_area.x);
+      if (focus_cell)
+        gtk_tree_view_column_focus_cell (column, focus_cell);
+
       if (event->state & GDK_CONTROL_MASK)
        {
          gtk_tree_view_real_set_cursor (tree_view, path, FALSE, TRUE);
@@ -2727,7 +2733,9 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
   GList *last_column;
   gint vertical_separator;
   gint horizontal_separator;
+  gint focus_line_width;
   gboolean allow_rules;
+  gboolean has_special_cell;
 
   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
 
@@ -2737,6 +2745,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                        "horizontal_separator", &horizontal_separator,
                        "vertical_separator", &vertical_separator,
                        "allow_rules", &allow_rules,
+                       "focus-line-width", &focus_line_width,
                        NULL);
 
   if (tree_view->priv->tree == NULL)
@@ -2822,6 +2831,18 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
 
       parity = _gtk_rbtree_node_find_parity (tree, node);
 
+      for (list = tree_view->priv->columns; list; list = list->next)
+        {
+         GtkTreeViewColumn *column = list->data;
+         gtk_tree_view_column_cell_set_cell_data (column,
+                                                  tree_view->priv->model,
+                                                  &iter,
+                                                  GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
+                                                  node->children?TRUE:FALSE);
+       }
+
+      has_special_cell = gtk_tree_view_has_special_cell (tree_view);
+
       for (list = tree_view->priv->columns; list; list = list->next)
        {
          GtkTreeViewColumn *column = list->data;
@@ -2843,13 +2864,6 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
           else
             flags &= ~GTK_CELL_RENDERER_SORTED;
 
-         gtk_tree_view_column_cell_set_cell_data (column,
-                                                  tree_view->priv->model,
-                                                  &iter,
-                                                  GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
-                                                  node->children?TRUE:FALSE);
-
-
          background_area.x = cell_offset;
          background_area.width = column->width;
 
@@ -2954,7 +2968,7 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
                                                 &event->area,
                                                 flags);
            }
-         if (node == cursor &&
+         if (node == cursor && has_special_cell &&
              ((column == tree_view->priv->focus_column &&
                GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
                GTK_WIDGET_HAS_FOCUS (widget)) ||
@@ -3027,6 +3041,35 @@ gtk_tree_view_bin_expose (GtkWidget      *widget,
             }
         }
 
+      /* draw the big row-spanning focus rectangle, if needed */
+      if (!has_special_cell && node == cursor &&
+         GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS) &&
+         GTK_WIDGET_HAS_FOCUS (widget))
+        {
+         gint width;
+         GtkStateType focus_rect_state;
+
+         focus_rect_state =
+           flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
+           (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
+            (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
+             GTK_STATE_NORMAL));
+
+         gdk_drawable_get_size (tree_view->priv->bin_window,
+                                &width, NULL);
+         gtk_paint_focus (widget->style,
+                          tree_view->priv->bin_window,
+                          focus_rect_state,
+                          NULL,
+                          widget,
+                          "treeview",
+                          0,
+                          BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
+                          width,
+                          MAX (BACKGROUND_HEIGHT (node),
+                               tree_view->priv->expander_size));
+       }
+
       y_offset += max_height;
       if (node->children)
        {
@@ -5192,6 +5235,25 @@ gtk_tree_view_forall (GtkContainer *container,
     }
 }
 
+/* Returns TRUE if the treeview contains no "special" (editable or activatable)
+ * cells. If so we draw one big row-spanning focus rectangle.
+ */
+static gboolean
+gtk_tree_view_has_special_cell (GtkTreeView *tree_view)
+{
+  GList *list;
+
+  for (list = tree_view->priv->columns; list; list = list->next)
+    {
+      if (!((GtkTreeViewColumn *)list->data)->visible)
+       continue;
+      if (_gtk_tree_view_column_count_special_cells (list->data))
+       return TRUE;
+    }
+
+  return FALSE;
+}
+
 /* Returns TRUE if the focus is within the headers, after the focus operation is
  * done
  */
@@ -7076,7 +7138,9 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
                                               &iter,
                                               GTK_RBNODE_FLAG_SET (cursor_node, GTK_RBNODE_IS_PARENT),
                                               cursor_node->children?TRUE:FALSE);
-      if (_gtk_tree_view_column_cell_focus (column, count))
+      if (_gtk_tree_view_column_cell_focus (column, count,
+                                           list->prev?TRUE:FALSE,
+                                           list->next?TRUE:FALSE))
        {
          tree_view->priv->focus_column = column;
          found_column = TRUE;
@@ -7091,10 +7155,11 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
 
   if (found_column)
     {
-      _gtk_tree_view_queue_draw_node (tree_view,
-                                    cursor_tree,
-                                    cursor_node,
-                                    NULL);
+      if (!gtk_tree_view_has_special_cell (tree_view))
+       _gtk_tree_view_queue_draw_node (tree_view,
+                                       cursor_tree,
+                                       cursor_node,
+                                       NULL);
       g_signal_emit (G_OBJECT (tree_view), tree_view_signals[CURSOR_CHANGED], 0);
     }
   gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
@@ -9246,11 +9311,47 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
                          GtkTreePath       *path,
                          GtkTreeViewColumn *focus_column,
                          gboolean           start_editing)
+{
+  gtk_tree_view_set_cursor_on_cell (tree_view, path, focus_column,
+                                   NULL, start_editing);
+}
+
+/**
+ * gtk_tree_view_set_cursor_on_cell:
+ * @tree_view: A #GtkTreeView
+ * @path: A #GtkTreePath
+ * @focus_column: A #GtkTreeViewColumn, or %NULL
+ * @focus_cell: A #GtkCellRenderer, or %NULL
+ * @start_editing: %TRUE if the specified cell should start being edited.
+ *
+ * Sets the current keyboard focus to be at @path, and selects it.  This is
+ * useful when you want to focus the user's attention on a particular row.  If
+ * @focus_column is not %NULL, then focus is given to the column specified by
+ * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
+ * contains 2 or more editable or activatable cells, then focus is given to
+ * the cell specified by @focus_cell. Additionally, if @focus_column is
+ * specified, and @start_editing is %TRUE, then editing should be started in
+ * the specified cell.  This function is often followed by
+ * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
+ * widget.  Please note that editing can only happen when the widget is
+ * realized.
+ **/
+void
+gtk_tree_view_set_cursor_on_cell (GtkTreeView       *tree_view,
+                                 GtkTreePath       *path,
+                                 GtkTreeViewColumn *focus_column,
+                                 GtkCellRenderer   *focus_cell,
+                                 gboolean           start_editing)
 {
   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
   g_return_if_fail (path != NULL);
   if (focus_column)
     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (focus_column));
+  if (focus_cell)
+    {
+      g_return_if_fail (focus_column);
+      g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
+    }
 
   gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
 
@@ -9267,12 +9368,13 @@ gtk_tree_view_set_cursor (GtkTreeView       *tree_view,
          }
       g_return_if_fail (column_in_tree);
       tree_view->priv->focus_column = focus_column;
+      if (focus_cell)
+       gtk_tree_view_column_focus_cell (focus_column, focus_cell);
       if (start_editing)
        gtk_tree_view_start_editing (tree_view, path);
     }
 }
 
-
 /**
  * gtk_tree_view_get_bin_window:
  * @tree_view: A #GtkTreeView
@@ -10418,8 +10520,6 @@ gtk_tree_view_search_iter (GtkTreeModel     *model,
   GtkTreePath *path;
 
   GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
-  GtkTreeViewColumn *column =
-    gtk_tree_view_get_column (tree_view, tree_view->priv->search_column);
 
   path = gtk_tree_model_get_path (model, iter);
   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
@@ -10634,11 +10734,22 @@ gtk_tree_view_start_editing (GtkTreeView *tree_view,
       retval = TRUE;
       if (editable_widget != NULL)
        {
+         gint left, right;
+         GdkRectangle area;
+         GtkCellRenderer *cell;
+
+         area = cell_area;
+         cell = _gtk_tree_view_column_get_edited_cell (tree_view->priv->focus_column);
+         _gtk_tree_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
+
+         area.x += left;
+         area.width -= right + left;
+
          gtk_tree_view_real_start_editing (tree_view,
                                            tree_view->priv->focus_column,
                                            cursor_path,
                                            editable_widget,
-                                           &cell_area,
+                                           &area,
                                            NULL,
                                            flags);
        }
index 69ef93b954b49fc576882ff67aaafc6d358114f3..750aa1c39e9cca3070be1b1faa29a757ce25b25f 100644 (file)
@@ -218,6 +218,11 @@ void                   gtk_tree_view_set_cursor                    (GtkTreeView
                                                                    GtkTreePath               *path,
                                                                    GtkTreeViewColumn         *focus_column,
                                                                    gboolean                   start_editing);
+void                   gtk_tree_view_set_cursor_on_cell            (GtkTreeView               *tree_view,
+                                                                   GtkTreePath               *path,
+                                                                   GtkTreeViewColumn         *focus_column,
+                                                                   GtkCellRenderer           *focus_cell,
+                                                                   gboolean                   start_editing);
 void                   gtk_tree_view_get_cursor                    (GtkTreeView               *tree_view,
                                                                    GtkTreePath              **path,
                                                                    GtkTreeViewColumn        **focus_column);
index eb2cc21a9d917f8377128f4e96db1a8cb4334b23..7f76fc6cf7dddf21cf7b53b201ba3325f0af52db 100644 (file)
@@ -68,6 +68,7 @@ struct _GtkTreeViewColumnCellInfo
   guint expand : 1;
   guint pack : 1;
   guint has_focus : 1;
+  guint in_editing_mode : 1;
 };
 
 /* Type methods */
@@ -113,6 +114,13 @@ static void gtk_tree_view_column_set_attributesv               (GtkTreeViewColum
 static GtkTreeViewColumnCellInfo *gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
                                                                      GtkCellRenderer   *cell_renderer);
 
+/* cell list manipulation */
+static GList *gtk_tree_view_column_cell_first                  (GtkTreeViewColumn      *tree_column);
+static GList *gtk_tree_view_column_cell_last                   (GtkTreeViewColumn      *tree_column);
+static GList *gtk_tree_view_column_cell_next                   (GtkTreeViewColumn      *tree_column,
+                                                               GList                  *current);
+static GList *gtk_tree_view_column_cell_prev                   (GtkTreeViewColumn      *tree_column,
+                                                               GList                  *current);
 
 
 static GtkObjectClass *parent_class = NULL;
@@ -1054,14 +1062,14 @@ _gtk_tree_view_column_has_editable_cell (GtkTreeViewColumn *column)
   return FALSE;
 }
 
+/* gets cell being edited */
 GtkCellRenderer *
-_gtk_tree_view_column_get_editable_cell (GtkTreeViewColumn *column)
+_gtk_tree_view_column_get_edited_cell (GtkTreeViewColumn *column)
 {
   GList *list;
 
   for (list = column->cell_list; list; list = list->next)
-    if (((GtkTreeViewColumnCellInfo *)list->data)->cell->mode ==
-       GTK_CELL_RENDERER_MODE_EDITABLE)
+    if (((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode)
       return ((GtkTreeViewColumnCellInfo *)list->data)->cell;
 
   return NULL;
@@ -1085,6 +1093,25 @@ _gtk_tree_view_column_count_special_cells (GtkTreeViewColumn *column)
   return i;
 }
 
+GtkCellRenderer *
+_gtk_tree_view_column_get_cell_at_pos (GtkTreeViewColumn *column,
+                                      gint               x)
+{
+  GList *list;
+  gint current_x = 0;
+
+  list = gtk_tree_view_column_cell_first (column);
+  for (; list; list = gtk_tree_view_column_cell_next (column, list))
+   {
+     GtkTreeViewColumnCellInfo *cellinfo = list->data;
+     if (current_x <= x && x <= current_x + cellinfo->real_width)
+       return cellinfo->cell;
+     current_x += cellinfo->real_width;
+   }
+
+  return NULL;
+}
+
 /* Public Functions */
 
 
@@ -1222,7 +1249,7 @@ gtk_tree_view_column_pack_end (GtkTreeViewColumn  *tree_column,
   g_object_ref (G_OBJECT (cell));
   gtk_object_sink (GTK_OBJECT (cell));
 
-  cell_info = g_new (GtkTreeViewColumnCellInfo, 1);
+  cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
   cell_info->cell = cell;
   cell_info->expand = expand ? TRUE : FALSE;
   cell_info->pack = GTK_PACK_END;
@@ -2351,23 +2378,53 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
   gint min_x, min_y, max_x, max_y;
   gint focus_line_width;
   gint dx;
+  gint special_cells;
 
   min_x = G_MAXINT;
   min_y = G_MAXINT;
   max_x = 0;
   max_y = 0;
 
-  real_cell_area = *cell_area;
-  real_background_area = *background_area;
-  dx = real_cell_area.x - real_background_area.x;
+  special_cells = _gtk_tree_view_column_count_special_cells (tree_column);
+
+  if (special_cells > 1 && action == CELL_ACTION_FOCUS)
+    {
+      GtkTreeViewColumnCellInfo *info = NULL;
+      gboolean found_has_focus = FALSE;
+
+      /* one should have focus */
+      for (list = tree_column->cell_list; list; list = list->next)
+        {
+         info = list->data;
+         if (info && info->has_focus)
+           {
+             found_has_focus = TRUE;
+             break;
+           }
+       }
+
+      if (!found_has_focus)
+        {
+         /* give the first one focus */
+         info = gtk_tree_view_column_cell_first (tree_column)->data;
+         info->has_focus = TRUE;
+       }
+    }
 
   gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
                        "focus-line-width", &focus_line_width,
                        NULL);
-  /* Find out how my extra space we have to allocate */
+
+  real_cell_area = *cell_area;
+  real_background_area = *background_area;
+  dx = real_cell_area.x - real_background_area.x - focus_line_width;
+
+  real_cell_area.x += focus_line_width;
+
+  /* Find out how many extra space we have to allocate */
   for (list = tree_column->cell_list; list; list = list->next)
     {
-      GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
+      GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
 
       if (! info->cell->visible)
        continue;
@@ -2377,10 +2434,13 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
       full_requested_width += info->requested_width;
     }
 
-  extra_space = cell_area->width - full_requested_width;
+  extra_space = background_area->width - full_requested_width;
   if (extra_space < 0)
     extra_space = 0;
+  else if (extra_space > 0 && expand_cell_count > 0)
+    extra_space /= expand_cell_count;
 
+  /* iterate list for GTK_PACK_START cells */
   for (list = tree_column->cell_list; list; list = list->next)
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
@@ -2391,15 +2451,12 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
       if (! info->cell->visible)
        continue;
 
-      real_cell_area.width = info->requested_width +
+      real_background_area.width = info->requested_width +
        (info->expand?extra_space:0);
-      info->real_width = real_cell_area.width;
-      real_cell_area.x += focus_line_width;
+      info->real_width = real_background_area.width;
 
-      real_background_area.width = real_cell_area.width;
-      real_background_area.x += focus_line_width;
-      if (!list->prev)
-       real_background_area.width += dx;
+      real_cell_area.width = real_background_area.width;
+      real_cell_area.width -= 2 * focus_line_width;
 
       if (action == CELL_ACTION_RENDER)
        {
@@ -2421,14 +2478,27 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
                                      &x_offset, &y_offset,
                                      &width, &height);
 
-         if (min_x > (real_cell_area.x + x_offset))
-           min_x = real_cell_area.x + x_offset;
-         if (max_x < real_cell_area.x + x_offset + width)
-           max_x = real_cell_area.x + x_offset + width;
-         if (min_y > (real_cell_area.y + y_offset))
-           min_y = real_cell_area.y + y_offset;
-         if (max_y < real_cell_area.y + y_offset + height)
-           max_y = real_cell_area.y + y_offset + height;
+         if (special_cells > 1)
+           {
+             if (info->has_focus)
+               {
+                 min_x = real_cell_area.x + x_offset;
+                 max_x = min_x + width;
+                 min_y = real_cell_area.y + y_offset;
+                 max_y = min_y + height;
+               }
+           }
+         else
+           {
+             if (min_x > (real_cell_area.x + x_offset))
+               min_x = real_cell_area.x + x_offset;
+             if (max_x < real_cell_area.x + x_offset + width)
+               max_x = real_cell_area.x + x_offset + width;
+             if (min_y > (real_cell_area.y + y_offset))
+               min_y = real_cell_area.y + y_offset;
+             if (max_y < real_cell_area.y + y_offset + height)
+               max_y = real_cell_area.y + y_offset + height;
+           }
        }
       else if (action == CELL_ACTION_EVENT)
        {
@@ -2436,9 +2506,9 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
 
          if (event)
            {
-             if (_gtk_tree_view_column_count_special_cells (tree_column) == 1)
+             if (special_cells == 1)
                {
-                 /* only 1 activatably cell -> whole column can activate */
+                 /* only 1 activatable cell -> whole column can activate */
                  if (cell_area->x <= ((GdkEventButton *)event)->x &&
                      cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
                    try_event = TRUE;
@@ -2450,11 +2520,11 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
                   */
                try_event = TRUE;
            }
-         else /* if (info->has_focus)*/
-           /* FIXME 73676: allow focusing individual cells */
-           {
-             try_event = TRUE;
-           }
+         else if (special_cells > 1 && info->has_focus)
+           try_event = TRUE;
+         else if (special_cells == 1)
+           try_event = TRUE;
+
          if (try_event)
            {
              gboolean visible, mode;
@@ -2488,15 +2558,20 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
                  if (*editable_widget != NULL)
                    {
                      g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
+                     info->in_editing_mode = TRUE;
+                     gtk_tree_view_column_focus_cell (tree_column, info->cell);
                      
                      return TRUE;
                    }
                }
            }
        }
-      real_cell_area.x += (info->requested_width + tree_column->spacing);
-      real_background_area.x += (info->requested_width + tree_column->spacing);
+
+      real_cell_area.x += (info->real_width + tree_column->spacing);
+      real_background_area.x += (info->real_width + tree_column->spacing);
     }
+
+  /* iterate list for PACK_END cells */
   for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
@@ -2507,10 +2582,13 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
       if (! info->cell->visible)
        continue;
 
-      real_cell_area.width = info->requested_width +
+      real_background_area.width = info->requested_width +
        (info->expand?extra_space:0);
-      info->real_width = real_cell_area.width;
-      real_background_area.width = real_background_area.width;
+      info->real_width = real_background_area.width;
+
+      real_cell_area.width = real_background_area.width;
+      real_cell_area.width -= 2 * focus_line_width;
+
       if (action == CELL_ACTION_RENDER)
        {
          gtk_cell_renderer_render (info->cell,
@@ -2531,19 +2609,100 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
                                      &x_offset, &y_offset,
                                      &width, &height);
 
-         if (min_x > (real_cell_area.x + x_offset))
-           min_x = real_cell_area.x + x_offset;
-         if (max_x < real_cell_area.x + x_offset + width)
-           max_x = real_cell_area.x + x_offset + width;
-         if (min_y > (real_cell_area.y + y_offset))
-           min_y = real_cell_area.y + y_offset;
-         if (max_y < real_cell_area.y + y_offset + height)
-           max_y = real_cell_area.y + y_offset + height;
+         if (special_cells > 1)
+           {
+             if (info->has_focus)
+               {
+                 min_x = real_cell_area.x + x_offset;
+                 max_x = min_x + width;
+                 min_y = real_cell_area.y + y_offset;
+                 max_y = min_y + height;
+               }
+           }
+         else
+           {
+             if (min_x > (real_cell_area.x + x_offset))
+               min_x = real_cell_area.x + x_offset;
+             if (max_x < real_cell_area.x + x_offset + width)
+               max_x = real_cell_area.x + x_offset + width;
+             if (min_y > (real_cell_area.y + y_offset))
+               min_y = real_cell_area.y + y_offset;
+             if (max_y < real_cell_area.y + y_offset + height)
+               max_y = real_cell_area.y + y_offset + height;
+           }
        }
-      real_cell_area.x += (info->requested_width + tree_column->spacing);
-      real_background_area.x += (info->requested_width + tree_column->spacing);
+      else if (action == CELL_ACTION_EVENT)
+        {
+         gboolean try_event = FALSE;
+
+         if (event)
+           {
+             if (special_cells == 1)
+               {
+                 /* only 1 activatable cell -> whole column can activate */
+                 if (cell_area->x <= ((GdkEventButton *)event)->x &&
+                     cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
+                   try_event = TRUE;
+               }
+             else if (real_cell_area.x <= ((GdkEventButton *)event)->x &&
+                 real_cell_area.x + real_cell_area.width > ((GdkEventButton *)event)->x)
+               /* only activate cell if the user clicked on an individual
+                * cell
+                */
+               try_event = TRUE;
+           }
+         else if (special_cells > 1 && info->has_focus)
+           try_event = TRUE;
+         else if (special_cells == 1)
+           try_event = TRUE;
+
+         if (try_event)
+           {
+             gboolean visible, mode;
+
+             g_object_get (G_OBJECT (info->cell),
+                           "visible", &visible,
+                           "mode", &mode,
+                           NULL);
+             if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+               {
+                 if (gtk_cell_renderer_activate (info->cell,
+                                                 event,
+                                                 tree_column->tree_view,
+                                                 path_string,
+                                                 background_area,
+                                                 cell_area,
+                                                 flags))
+                   return TRUE;
+               }
+             else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
+               {
+                 *editable_widget =
+                   gtk_cell_renderer_start_editing (info->cell,
+                                                    event,
+                                                    tree_column->tree_view,
+                                                    path_string,
+                                                    background_area,
+                                                    cell_area,
+                                                    flags);
+
+                 if (*editable_widget != NULL)
+                   {
+                     g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
+                     info->in_editing_mode = TRUE;
+                     gtk_tree_view_column_focus_cell (tree_column, info->cell);
+
+                     return TRUE;
+                   }
+               }
+           }
+       }
+
+      real_cell_area.x += (info->real_width + tree_column->spacing);
+      real_background_area.x += (info->real_width + tree_column->spacing);
     }
 
+  /* fill focus_rectangle when required */
   if (action == CELL_ACTION_FOCUS)
     {
       if (min_x >= max_x || min_y >= max_y)
@@ -2622,14 +2781,218 @@ _gtk_tree_view_column_cell_event (GtkTreeViewColumn  *tree_column,
                                                   path_string);
 }
 
+/* cell list manipulation */
+static GList *
+gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column)
+{
+  GList *list = tree_column->cell_list;
+
+  /* first GTK_PACK_START cell we find */
+  for ( ; list; list = list->next)
+    {
+      GtkTreeViewColumnCellInfo *info = list->data;
+      if (info->pack == GTK_PACK_START)
+       return list;
+    }
+
+  /* hmm, else the *last* GTK_PACK_END cell */
+  list = g_list_last (tree_column->cell_list);
+
+  for ( ; list; list = list->prev)
+    {
+      GtkTreeViewColumnCellInfo *info = list->data;
+      if (info->pack == GTK_PACK_END)
+       return list;
+    }
+
+  return NULL;
+}
+
+static GList *
+gtk_tree_view_column_cell_last (GtkTreeViewColumn *tree_column)
+{
+  GList *list = tree_column->cell_list;
+
+  /* *first* GTK_PACK_END cell we find */
+  for ( ; list ; list = list->next)
+    {
+      GtkTreeViewColumnCellInfo *info = list->data;
+      if (info->pack == GTK_PACK_END)
+       return list;
+    }
+
+  /* hmm, else the last GTK_PACK_START cell */
+  list = g_list_last (tree_column->cell_list);
+
+  for ( ; list; list = list->prev)
+    {
+      GtkTreeViewColumnCellInfo *info = list->data;
+      if (info->pack == GTK_PACK_START)
+       return list;
+    }
+
+  return NULL;
+}
+
+static GList *
+gtk_tree_view_column_cell_next (GtkTreeViewColumn *tree_column,
+                               GList             *current)
+{
+  GList *list;
+  GtkTreeViewColumnCellInfo *info = current->data;
+
+  if (info->pack == GTK_PACK_START)
+    {
+      for (list = current->next; list; list = list->next)
+        {
+         GtkTreeViewColumnCellInfo *inf = list->data;
+         if (inf->pack == GTK_PACK_START)
+           return list;
+       }
+
+      /* out of GTK_PACK_START cells, get *last* GTK_PACK_END one */
+      list = g_list_last (tree_column->cell_list);
+      for (; list; list = list->prev)
+        {
+         GtkTreeViewColumnCellInfo *inf = list->data;
+         if (inf->pack == GTK_PACK_END)
+           return list;
+       }
+    }
+
+  for (list = current->prev; list; list = list->prev)
+    {
+      GtkTreeViewColumnCellInfo *inf = list->data;
+      if (inf->pack == GTK_PACK_END)
+       return list;
+    }
+
+  return NULL;
+}
+
+static GList *
+gtk_tree_view_column_cell_prev (GtkTreeViewColumn *tree_column,
+                               GList             *current)
+{
+  GList *list;
+  GtkTreeViewColumnCellInfo *info = current->data;
+
+  if (info->pack == GTK_PACK_END)
+    {
+      for (list = current->next; list; list = list->next)
+        {
+         GtkTreeViewColumnCellInfo *inf = list->data;
+         if (inf->pack == GTK_PACK_END)
+           return list;
+       }
+
+      /* out of GTK_PACK_END, get last GTK_PACK_START one */
+      list = g_list_last (tree_column->cell_list);
+      for ( ; list; list = list->prev)
+        {
+         GtkTreeViewColumnCellInfo *inf = list->data;
+         if (inf->pack == GTK_PACK_START)
+           return list;
+       }
+    }
+
+  for (list = current->prev; list; list = list->prev)
+    {
+      GtkTreeViewColumnCellInfo *inf = list->data;
+      if (inf->pack == GTK_PACK_START)
+       return list;
+    }
+
+  return NULL;
+}
 
 gboolean
 _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
-                                 gint               direction)
+                                 gint               direction,
+                                 gboolean           left,
+                                 gboolean           right)
 {
-  /* FIXME 73676: allow focusing individual cells */
+  gint count;
+
+  count = _gtk_tree_view_column_count_special_cells (tree_column);
+
+  /* if we are the current focus column and have multiple editable cells,
+   * try to select the next one, else move the focus to the next column
+   */
   if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
-    return FALSE;
+    {
+      if (count > 1)
+        {
+          GList *next, *prev;
+         GList *list = tree_column->cell_list;
+         GtkTreeViewColumnCellInfo *info = NULL;
+
+         /* find current focussed cell */
+         for ( ; list; list = list->next)
+           {
+             info = list->data;
+             if (info->has_focus)
+               break;
+           }
+
+         /* not a focussed cell in the focus column? */
+         if (!list || !info || !info->has_focus)
+           return FALSE;
+
+         next = gtk_tree_view_column_cell_next (tree_column, list);
+         prev = gtk_tree_view_column_cell_prev (tree_column, list);
+
+         info->has_focus = FALSE;
+         if (direction > 0 && next)
+           {
+             info = next->data;
+             info->has_focus = TRUE;
+             return TRUE;
+           }
+         else if (direction > 0 && !next && !right)
+           {
+             /* keep focus on latest cell */
+             info = gtk_tree_view_column_cell_last (tree_column)->data;
+             info->has_focus = TRUE;
+             return TRUE;
+           }
+         else if (direction < 0 && prev)
+           {
+             info = prev->data;
+             info->has_focus = TRUE;
+             return TRUE;
+           }
+         else if (direction < 0 && !prev && !left)
+           {
+             /* keep focus on first cell */
+             info = gtk_tree_view_column_cell_first (tree_column)->data;
+             info->has_focus = TRUE;
+             return TRUE;
+           }
+       }
+      return FALSE;
+    }
+
+  /* we get focus, if we have multiple editable cells, give the correct one
+   * focus
+   */
+  if (count > 1)
+    {
+      GList *list = tree_column->cell_list;
+
+      /* clear focus first */
+      for ( ; list ; list = list->next)
+        {
+         GtkTreeViewColumnCellInfo *info = list->data;
+         if (info->has_focus)
+           info->has_focus = FALSE;
+       }
+
+      if (direction > 0)
+       ((GtkTreeViewColumnCellInfo *)gtk_tree_view_column_cell_first (tree_column)->data)->has_focus = TRUE;
+      else if (direction < 0)
+       ((GtkTreeViewColumnCellInfo *)gtk_tree_view_column_cell_last (tree_column)->data)->has_focus = TRUE;
+    }
   return TRUE;
 }
 
@@ -2708,6 +3071,8 @@ gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
 {
   GList *list;
 
+  g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
+
   for (list = tree_column->cell_list; list; list = list->next)
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
@@ -2719,6 +3084,53 @@ gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
   return FALSE;
 }
 
+/**
+ * gtk_tree_view_column_focus_cell:
+ * @tree_view: A #GtkTreeView
+ * @cell: A #GtkCellRenderer
+ *
+ * Sets the current keyboard focus to be at @cell, if the column contains
+ * 2 or more editable and activatable cells.
+ **/
+void
+gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
+                                GtkCellRenderer   *cell)
+{
+  GList *list;
+  gboolean found_cell = FALSE;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
+
+  if (_gtk_tree_view_column_count_special_cells (tree_column) < 2)
+    return;
+
+  for (list = tree_column->cell_list; list; list = list->next)
+    {
+      GtkTreeViewColumnCellInfo *info = list->data;
+
+      if (info->cell == cell)
+        {
+         info->has_focus = TRUE;
+         found_cell = TRUE;
+         break;
+       }
+    }
+
+  if (found_cell)
+    {
+      for (list = tree_column->cell_list; list; list = list->next)
+        {
+         GtkTreeViewColumnCellInfo *info = list->data;
+
+         if (info->cell != cell)
+           info->has_focus = FALSE;
+        }
+
+      /* FIXME: redraw? */
+    }
+}
+
 void
 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
                                      gboolean           install_handler)
@@ -2759,9 +3171,13 @@ _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
 void
 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
 {
+  GList *list;
+
   g_return_if_fail (tree_column->editable_widget != NULL);
 
   tree_column->editable_widget = NULL;
+  for (list = tree_column->cell_list; list; list = list->next)
+    ((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode = FALSE;
 }
 
 void
@@ -2775,8 +3191,9 @@ _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
   if (left)
     {
       *left = 0;
+      list = gtk_tree_view_column_cell_first (column);
 
-      for (list = column->cell_list; list; list = list->next)
+      for (; list; list = gtk_tree_view_column_cell_next (column, list))
         {
          GtkTreeViewColumnCellInfo *info =
            (GtkTreeViewColumnCellInfo *)list->data;
@@ -2790,9 +3207,12 @@ _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
 
   if (right)
     {
+      GList *next;
+
       *right = 0;
+      list = gtk_tree_view_column_cell_first (column);
 
-      for (list = column->cell_list; list; list = list->next)
+      for (; list; list = gtk_tree_view_column_cell_next (column, list))
         {
          GtkTreeViewColumnCellInfo *info =
            (GtkTreeViewColumnCellInfo *)list->data;
@@ -2802,10 +3222,11 @@ _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
        }
 
       /* skip cell */
-      if (list && list->next)
+      next = gtk_tree_view_column_cell_next (column, list);
+      if (list && next)
         {
-         list = list->next;
-         for ( ; list; list = list->next)
+         list = next;
+         for ( ; list; list = gtk_tree_view_column_cell_next (column, list))
            {
              GtkTreeViewColumnCellInfo *info =
                (GtkTreeViewColumnCellInfo *)list->data;
index fd1f48c2bb0b95216b8d6fb14df0005758f20001..22d20ef7043fe32133e1381de4a5a198d799c290 100644 (file)
@@ -217,6 +217,8 @@ void                    gtk_tree_view_column_cell_get_size       (GtkTreeViewCol
                                                                  gint                    *width,
                                                                  gint                    *height);
 gboolean                gtk_tree_view_column_cell_is_visible     (GtkTreeViewColumn       *tree_column);
+void                    gtk_tree_view_column_focus_cell          (GtkTreeViewColumn       *tree_column,
+                                                                 GtkCellRenderer         *cell);
 
 #ifdef __cplusplus
 }
index 9163fd2c9bd239b73a741d3a8d606cbc603b3b5f..2b8f114ccc0228c4f908882673a16107a2bf0708 100644 (file)
@@ -8,6 +8,7 @@ typedef struct {
 enum {
   STRING_COLUMN,
   IS_EDITABLE_COLUMN,
+  PIXBUF_COLUMN,
   NUM_COLUMNS
 };
 
@@ -24,21 +25,29 @@ static ListEntry model_strings[] =
 static GtkTreeModel *
 create_model (void)
 {
-  GtkListStore *model;
+  GtkTreeStore *model;
   GtkTreeIter iter;
   gint i;
+  GdkPixbuf *foo;
+  GtkWidget *blah;
+
+  blah = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  foo = gtk_widget_render_icon (blah, GTK_STOCK_NEW, GTK_ICON_SIZE_MENU, NULL);
+  gtk_widget_destroy (blah);
   
-  model = gtk_list_store_new (NUM_COLUMNS,
+  model = gtk_tree_store_new (NUM_COLUMNS,
                              G_TYPE_STRING,
-                             G_TYPE_BOOLEAN);
+                             G_TYPE_BOOLEAN,
+                             GDK_TYPE_PIXBUF);
 
   for (i = 0; model_strings[i].string != NULL; i++)
     {
-      gtk_list_store_append (model, &iter);
+      gtk_tree_store_append (model, &iter, NULL);
 
-      gtk_list_store_set (model, &iter,
+      gtk_tree_store_set (model, &iter,
                          STRING_COLUMN, model_strings[i].string,
                          IS_EDITABLE_COLUMN, model_strings[i].is_editable,
+                         PIXBUF_COLUMN, foo,
                          -1);
     }
   
@@ -59,7 +68,7 @@ toggled (GtkCellRendererToggle *cell,
   gtk_tree_model_get (model, &iter, IS_EDITABLE_COLUMN, &value, -1);
 
   value = !value;
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter, IS_EDITABLE_COLUMN, value, -1);
+  gtk_tree_store_set (GTK_TREE_STORE (model), &iter, IS_EDITABLE_COLUMN, value, -1);
 
   gtk_tree_path_free (path);
 }
@@ -75,7 +84,7 @@ edited (GtkCellRendererText *cell,
   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
 
   gtk_tree_model_get_iter (model, &iter, path);
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter, STRING_COLUMN, new_text, -1);
+  gtk_tree_store_set (GTK_TREE_STORE (model), &iter, STRING_COLUMN, new_text, -1);
 
   gtk_tree_path_free (path);
 }
@@ -102,6 +111,7 @@ main (gint argc, gchar **argv)
   GtkWidget *tree_view;
   GtkTreeModel *tree_model;
   GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
   
   gtk_init (&argc, &argv);
 
@@ -118,18 +128,39 @@ main (gint argc, gchar **argv)
   tree_view = gtk_tree_view_new_with_model (tree_model);
   g_signal_connect (tree_view, "button_press_event", G_CALLBACK (button_press_event), NULL);
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
-  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
+  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), TRUE);
 
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                              -1, "String",
-                                              renderer,
-                                              "text", STRING_COLUMN,
-                                              "editable", IS_EDITABLE_COLUMN,
-                                              NULL);
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (column, "String");
+
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_set_attributes (column, renderer,
+                                      "pixbuf", PIXBUF_COLUMN, NULL);
 
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_set_attributes (column, renderer,
+                                      "text", STRING_COLUMN,
+                                      "editable", IS_EDITABLE_COLUMN,
+                                      NULL);
+  g_signal_connect (G_OBJECT (renderer), "edited",
+                   G_CALLBACK (edited), tree_model);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_set_attributes (column, renderer,
+                                      "text", STRING_COLUMN,
+                                      "editable", IS_EDITABLE_COLUMN,
+                                      NULL);
   g_signal_connect (G_OBJECT (renderer), "edited",
                    G_CALLBACK (edited), tree_model);
+
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_set_attributes (column, renderer,
+                                      "pixbuf", PIXBUF_COLUMN, NULL);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+
   renderer = gtk_cell_renderer_toggle_new ();
   g_signal_connect (G_OBJECT (renderer), "toggled",
                    G_CALLBACK (toggled), tree_model);
@@ -145,7 +176,7 @@ main (gint argc, gchar **argv)
   gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
   
   gtk_window_set_default_size (GTK_WINDOW (window),
-                              650, 400);
+                              800, 175);
 
   gtk_widget_show_all (window);
   gtk_main ();